package com.ty.dao;

import com.alibaba.druid.pool.DruidDataSource;

import java.io.InputStream;
import java.sql.*;
import java.util.List;
import java.util.Properties;

/**
 * @author 田野
 */
public class DBUtils {
    /**
     * 1、定义变量
     */
    private Connection connection;
    protected PreparedStatement preparedStatement;
    protected ResultSet resultSet;
    /**
     * 存储受影响的行数
     */
    private int count;
    private static String url;
    private static String user;
    private static String password;
    private static String driverName;
    /**
     * Druid
     */
    private static DruidDataSource druidDataSource = new DruidDataSource();

    // 2、加载驱动
    static {
        // 使用静态代码块，保证最开始就开始加载驱动
        try {
            // Druid
            InputStream inputStream = DBUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(inputStream);

            driverName = properties.getProperty("drivercalss");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");

            // Druid
            druidDataSource.setUsername(user);
            druidDataSource.setPassword(password);
            druidDataSource.setUrl(url);
            druidDataSource.setDriverClassName(driverName);

            // 设置连接池的参数
            druidDataSource.setInitialSize(2);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 3、获取连接，利用 protected 修饰 保证其职能由其子类调用
     * @return
     */
    protected Connection getConnection() {
        try {
            // Druid
            connection = druidDataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 4、得到预状态通道方法
     * @param sql
     * @return
     */
    protected PreparedStatement getPreparedStatement(String sql) {
        getConnection();
        try {
            // 在DBUtils中，获得预状态通道的时候，可以传入一个静态属性：
            // 新增数据的id值,即Statement.RETURN_GENERATED_KEYS
            // 然后再Dao层
            preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            /*preparedStatement = connection.prepareStatement(sql);*/
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return preparedStatement;
    }

    /**
     * 5、绑定参数 List保存的是给占位符所赋的值
     * @param list
     */
    protected void setPreparedStatement(List list) {
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                try {
                    preparedStatement.setObject(i + 1, list.get(i));
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 6、执行操作 DML
     * 数据操纵语言 （Data Manipulation Language, DML）是用于数据库操作，
     * 对数据库其中的对象和数据运行访问工作的编程语句，
     * 通常是数据库专用编程语言之中的一个子集，
     * 例如在信息软件产业通行标准的 SQL 语言中，
     * 以INSERT、UPDATE、DELETE三种指令为核心，
     * 分别代表插入 (意指新增或创建)、更新 (修改)与删除 (销毁)。
     * @param sql
     * @param list
     * @return
     */
    protected int update(String sql, List list) {
        try {
            getPreparedStatement(sql);
            setPreparedStatement(list);
            count = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 7、DQL
     * @param sql
     * @param list
     * @return
     */
    protected ResultSet query(String sql, List list) {
        try {
            getPreparedStatement(sql);
            setPreparedStatement(list);
            resultSet = preparedStatement.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return resultSet;
    }

    /**
     * 8、关闭资源
     */
    protected void closeAll() {
        try {
            if (connection != null) {
                connection.close();
            }

            if (preparedStatement != null) {
                preparedStatement.close();
            }

            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}
